﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using InstallManager.Msi;
using System.Reflection;
using System.IO;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace InstallerGUI2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MsiInstallerSession msiInstallSession;
        string msiFile;
        public ObservableCollection<String> Messages;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
           
        }
        private void ExtractFiles(out string msiPath)
        {
            var rss = Assembly.GetExecutingAssembly().GetManifestResourceStream("InstallerGUI2.ApplicationSetup.msi");
            using (var fs = File.Create(msiPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "ApplicationSetup.msi")))
            {
                rss.CopyTo(fs);
            }
        }

        private void PrepareInstall()
        {

            msiInstallSession.OnMsiMessage += new EventHandler<MsiMessageEventArgs>(msiInstallSession_OnMsiMessage);
            msiInstallSession.OnProgressMessage += new EventHandler<MsiMessageEventArgs>(msiInstallSession_OnProgressMessage);
            msiInstallSession.OnActionStartMessage += new EventHandler<MsiMessageEventArgs>(msiInstallSession_OnActionStartMessage);
            msiInstallSession.OnCommonDataMessage += new EventHandler<MsiMessageEventArgs>(msiInstallSession_OnCommonDataMessage);
            msiInstallSession.OnInstallCompleted += new EventHandler<InstallCompletedEventArgs>(msiInstallSession_OnInstallCompleted);

        }

        void msiInstallSession_OnCommonDataMessage(object sender, MsiMessageEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate()
            {
                Process_CommonData_Message(e);
                scwBackground.ScrollToBottom();
            }), null);
            
        }

        void msiInstallSession_OnActionStartMessage(object sender, MsiMessageEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate()
            {
                ProcessActionStartMessage(e);
                scwBackground.ScrollToBottom();
            }), null);
            
        }

        void msiInstallSession_OnProgressMessage(object sender, MsiMessageEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate()
            {
                ProcessProgressMessage(e);
                scwBackground.ScrollToBottom();
            }), null);
            
        }

        void msiInstallSession_OnInstallCompleted(object sender, InstallCompletedEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate()
            {
                tbInstallUninstall.Text = "Finished!";
                animGrid.Visibility = Visibility.Collapsed;
            }), null);
        }

        void msiInstallSession_OnMsiMessage(object sender, MsiMessageEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate()
            {
                ProcessMessages(e);
                scwBackground.ScrollToBottom();
            }), null);

        }

        private void ProcessMessages(MsiMessageEventArgs e)
        {
            switch (e.MessageType)
            {
               
                case InstallManager.Msi.MsiInstallMessage.Error:
                case InstallManager.Msi.MsiInstallMessage.FatalExit:
                case InstallManager.Msi.MsiInstallMessage.FilesInUse:
                case InstallManager.Msi.MsiInstallMessage.Info:
                case InstallManager.Msi.MsiInstallMessage.Initialize:
                case InstallManager.Msi.MsiInstallMessage.OutOfDiskSpace:
                case InstallManager.Msi.MsiInstallMessage.ResolveSource:
                case InstallManager.Msi.MsiInstallMessage.ShowDialog:
                case InstallManager.Msi.MsiInstallMessage.Terminate:
                case InstallManager.Msi.MsiInstallMessage.User:
                case InstallManager.Msi.MsiInstallMessage.Warning:
                case InstallManager.Msi.MsiInstallMessage.ActionData:
                    Messages.Add(e.UIFlags +"//"+ e.Message);
                    break;
                default:
                   
                    break;
            }
            
        }
        private void Process_CommonData_Message(MsiMessageEventArgs e)
        {
            var msg = MsiCommonDataMessage.Parse(e.Message);
            Messages.Add(e.UIFlags + "//" + "Common Data -----" + msg.ToString());
        }

        private void ProcessActionStartMessage(MsiMessageEventArgs e)
        {
            Messages.Add(e.UIFlags + "//" + "Action ----" + new MsiActionMessage(e.Message).ToString());
        }

        private void ProcessProgressMessage(MsiMessageEventArgs e)
        {
            MsiProgressMessage pm = new MsiProgressMessage(e.Message);
            Messages.Add(e.UIFlags + "//"+"Progress -----" + pm.ToString());
        }
        private void AsynchInstall()
        {
            BackgroundWorker bgw = new BackgroundWorker();
            bgw.DoWork += (s, e) =>
            {
                msiInstallSession.Install();
            };
            bgw.RunWorkerAsync();
        }
        private void AsynchUninstall()
        {
            BackgroundWorker bgw = new BackgroundWorker();
            bgw.DoWork += (s, e) =>
            {
                msiInstallSession.UnInstall();

            };
            bgw.RunWorkerAsync();
        }
      

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            btnStart.Visibility = Visibility.Collapsed;
            animGrid.Visibility = System.Windows.Visibility.Visible;
            Messages = new ObservableCollection<string>();
            this.DataContext = Messages;
            ExtractFiles(out msiFile);
            msiInstallSession = new MsiInstallerSession(msiFile);
            PrepareInstall();
            if (msiInstallSession.IsInstalled)
            {
                tbInstallUninstall.Text = "Uninstalling...";
                AsynchUninstall();
            }
            else
            {
                tbInstallUninstall.Text = "Installing...";
                AsynchInstall();
            }
            
        }
    }
}
